//
//  AssetTranslationDelegate.swift
//  GifUsage
//
//  Created by han on 2020/12/21.
//  Copyright © 2020 Ting Han. All rights reserved.
//

import UIKit
import Photos

class AssetTranslationDelegate: NSObject {
    private var assetTransitioning = AssetTransitioning()
    private weak var navigationController: UINavigationController?
    
    init(navigationController: UINavigationController) {
        super.init()
        self.navigationController = navigationController
    }
    
}

extension AssetTranslationDelegate: UINavigationControllerDelegate {
    func navigationController(_ navigationController: UINavigationController, interactionControllerFor animationController: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? {
        return nil
    }
    
    func navigationController(_ navigationController: UINavigationController, animationControllerFor operation: UINavigationController.Operation, from fromVC: UIViewController, to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? {
        switch operation {
        case .push:
            assetTransitioning.translationType = .push
            guard  fromVC is AssetGridViewController, toVC is AssetViewController else { return nil }
            return assetTransitioning
        case .pop:
            return nil
//            assetTransitioning.translationType = .pop
//            guard  fromVC is AssetViewController, toVC is AssetGridViewController else { return nil }
//            return assetTransitioning
        case .none:
            break
        @unknown default:
            break
        }
        return nil
    }
}

class AssetTransitioning: NSObject {
    enum TranslationType {
        case push
        case pop
    }
    
    var duration: TimeInterval!
    var translationType: TranslationType!
    
    var isAnimation: Bool = false
    
    init(duration: TimeInterval = 0.35, translationType: TranslationType = .push) {
        super.init()
        self.duration = duration
        self.translationType = translationType
    }
    
    private let imageManager = PHCachingImageManager()
}

extension AssetTransitioning: UIViewControllerAnimatedTransitioning {
    func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
        return duration
    }
    
    func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
        guard let fromViewController = transitionContext.viewController(forKey: .from), let toViewController = transitionContext.viewController(forKey: .to) else { return }
        navigationTransitioning(fromVC: fromViewController, toVC: toViewController, transitionContext: transitionContext)
    }
    
    func navigationTransitioning(fromVC: UIViewController, toVC: UIViewController, transitionContext: UIViewControllerContextTransitioning) {
        switch translationType {
        case .push:
            pushTransitioning(fromVC: fromVC, toVC: toVC, transitionContext: transitionContext)
        case .pop:
            popTransitioning(fromVC: fromVC, toVC: toVC, transitionContext: transitionContext)
        case .none:
            break
        }
    }
    
    func pushTransitioning(fromVC: UIViewController, toVC: UIViewController, transitionContext: UIViewControllerContextTransitioning) {
        guard let gridVC = fromVC as? AssetGridViewController, let assetVC = toVC as? AssetViewController  else {
            return
        }
        guard let fromView = gridVC.view, let toView = assetVC.view else { return  }
        
        let containerView = transitionContext.containerView
        let rect = containerView.bounds
        
        guard let fromCollection = fromView.subviews.filter({ $0 is UICollectionView }).first as? UICollectionView else { return }
        guard let toCollection = toView.subviews.filter({ $0 is UICollectionView }).first as? UICollectionView else { return }
        let currentIndex = assetVC.currentIndex
        let cell = fromCollection.cellForItem(at: IndexPath(item: currentIndex, section: 0)) as? AssetGridCell
        guard let imageView = cell?.imageView else { return }
        let imageFrame = imageView.convert(imageView.bounds, to: containerView)
        let panImageView = UIImageView(frame: imageFrame)
        panImageView.contentMode = .scaleAspectFill
       
        let asset = gridVC.fetchResult[currentIndex]
        let aimRect = createActuralImageRect(asset: asset, containerRect: rect)
        let scale = UIScreen.main.scale
        getImage(asset: asset, targetSize: CGSize(width: scale * rect.width, height: scale * rect.height)) { (image) in
            panImageView.image = image
        }
        
        toView.alpha = 0
        toCollection.alpha = 0
        containerView.addSubview(toView)
        containerView.insertSubview(panImageView, aboveSubview: toView)
        isAnimation = true
        UIView.animate(withDuration: self.transitionDuration(using: transitionContext), animations: {
            toView.alpha = 1
            panImageView.frame = aimRect
        }) { (_) in
            if transitionContext.transitionWasCancelled {
                panImageView.frame = imageFrame
            } else {
                panImageView.frame = aimRect
            }
            toView.alpha = 1
            toCollection.alpha = 1
            transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
            UIView.animate(withDuration: 0.2) {
                panImageView.alpha = 0
            } completion: { _ in
                panImageView.removeFromSuperview()
            }
            self.isAnimation = false
        }
    }
    
    
    
    func popTransitioning(fromVC: UIViewController, toVC: UIViewController, transitionContext: UIViewControllerContextTransitioning) {
        guard let assetVC = fromVC as? AssetViewController, let gridVC = toVC as? AssetGridViewController else {
            return
        }
        guard  let fromView = assetVC.view, let toView = gridVC.view else { return }
        
        let containerView = transitionContext.containerView
        let rect = containerView.bounds
        
        guard let fromCollection = fromView.subviews.filter({ $0 is UICollectionView }).first as? UICollectionView else { return }
        guard let toCollection = toView.subviews.filter({ $0 is UICollectionView }).first as? UICollectionView else { return }
        let currentIndex = assetVC.currentIndex
        let cell = fromCollection.cellForItem(at: IndexPath(item: currentIndex, section: 0)) as? AssetCell
        let toCell = toCollection.cellForItem(at: IndexPath(item: currentIndex, section: 0)) as? AssetGridCell
        
        let panView = cell?.copyDisplayView() ?? UIView(frame: rect)
       
        containerView.addSubview(toView)
        containerView.bringSubviewToFront(fromView)
        containerView.insertSubview(panView, aboveSubview: fromView)
        let aimRect = toCell?.imageView.convert(toCell?.imageView.bounds ?? .zero, to: keyWindow) ?? .zero
        fromCollection.alpha = 0
        isAnimation = true
        UIView.animate(withDuration: self.transitionDuration(using: transitionContext), animations: {
            fromView.alpha = 0
            panView.frame = aimRect
        }) { (_) in
            if transitionContext.transitionWasCancelled {
                panView.frame = rect
                fromCollection.alpha = 1
                fromView.alpha = 1
            } else {
                panView.frame = aimRect
                fromCollection.alpha = 0
                fromView.alpha = 0
            }
            transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
//            UIView.animate(withDuration: 0.2) {
//                panView.alpha = 0
//            } completion: { _ in
//                panView.removeFromSuperview()
//            }
            self.isAnimation = false
        }
    }
    
}

extension AssetTransitioning {
    func createActuralImageRect(asset: PHAsset, containerRect: CGRect) -> CGRect {
        let assetRatio = CGFloat(asset.pixelWidth) / CGFloat(asset.pixelHeight)
        var realTargetSize = CGSize.zero
        if containerRect.width / assetRatio <= containerRect.height {
             realTargetSize = CGSize(width: containerRect.width, height: containerRect.width / assetRatio)
        } else {
             realTargetSize = CGSize(width: containerRect.height * assetRatio, height: containerRect.height)
        }
        let aimRect = CGRect(origin: CGPoint(x: (containerRect.width - realTargetSize.width) / 2, y: (containerRect.height - realTargetSize.height) / 2), size: realTargetSize)
        return aimRect
    }
    
    func getImage(asset: PHAsset, targetSize: CGSize, resultHandler: @escaping (UIImage) -> Void) {
        imageManager.requestImage(for: asset, targetSize: targetSize, contentMode: .aspectFit, options: nil) { (image, _) in
            guard let image = image else { return }
            resultHandler(image)
        }
    }
    
    var keyWindow: UIWindow {
        if #available(iOS 13, *) {
            return UIApplication.shared.windows.first!
        } else {
            return UIApplication.shared.keyWindow!
        }
    }
}

//extension AssetTranslation: UIPercentDrivenInteractiveTransition {
//
//}




